package com.kexilo.core.common.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMQ配置
 * 
 * @author Kexilo
 */
@Configuration
@ConditionalOnProperty(prefix = "mq", name = "enabled", havingValue = "true", matchIfMissing = true)
public class RabbitConfig {
    
    private static final Logger log = LoggerFactory.getLogger(RabbitConfig.class);

    @Value("${mq.exchange.user-operation:user.operation.exchange}")
    private String userOperationExchange;

    @Value("${mq.queue.audit-log:audit.log.queue}")
    private String auditLogQueue;

    @Value("${mq.queue.login-log:login.log.queue}")
    private String loginLogQueue;

    @Value("${mq.queue.notification:notification.queue}")
    private String notificationQueue;

    @Value("${mq.routing-key.audit:user.*.audit}")
    private String auditRoutingKey;

    @Value("${mq.routing-key.login:user.*.login}")
    private String loginRoutingKey;

    @Value("${mq.routing-key.notification:user.*.notification}")
    private String notificationRoutingKey;

    // 死信交换机和队列
    private static final String DLX_EXCHANGE = "dlx.exchange";
    private static final String AUDIT_LOG_DLQ = "audit.log.dlq";
    private static final String LOGIN_LOG_DLQ = "login.log.dlq";
    private static final String NOTIFICATION_DLQ = "notification.dlq";

    /**
     * 用户操作主题交换机
     */
    @Bean
    public TopicExchange userOperationExchange() {
        return ExchangeBuilder
                .topicExchange(userOperationExchange)
                .durable(true)
                .build();
    }

    /**
     * 死信交换机
     */
    @Bean
    public DirectExchange dlxExchange() {
        return ExchangeBuilder
                .directExchange(DLX_EXCHANGE)
                .durable(true)
                .build();
    }

    /**
     * 审计日志队列
     */
    @Bean
    public Queue auditLogQueue() {
        return QueueBuilder
                .durable(auditLogQueue)
                .withArgument("x-message-ttl", 86400000) // 24小时TTL
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", AUDIT_LOG_DLQ)
                .withArgument("x-max-retries", 3)
                .build();
    }

    /**
     * 登录日志队列
     */
    @Bean
    public Queue loginLogQueue() {
        return QueueBuilder
                .durable(loginLogQueue)
                .withArgument("x-message-ttl", 86400000) // 24小时TTL
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", LOGIN_LOG_DLQ)
                .withArgument("x-max-retries", 3)
                .build();
    }

    /**
     * 通知队列
     */
    @Bean
    public Queue notificationQueue() {
        return QueueBuilder
                .durable(notificationQueue)
                .withArgument("x-message-ttl", 3600000) // 1小时TTL
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                .withArgument("x-dead-letter-routing-key", NOTIFICATION_DLQ)
                .withArgument("x-max-retries", 3)
                .build();
    }

    /**
     * 审计日志死信队列
     */
    @Bean
    public Queue auditLogDeadLetterQueue() {
        return QueueBuilder.durable(AUDIT_LOG_DLQ).build();
    }

    /**
     * 登录日志死信队列
     */
    @Bean
    public Queue loginLogDeadLetterQueue() {
        return QueueBuilder.durable(LOGIN_LOG_DLQ).build();
    }

    /**
     * 通知死信队列
     */
    @Bean
    public Queue notificationDeadLetterQueue() {
        return QueueBuilder.durable(NOTIFICATION_DLQ).build();
    }

    /**
     * 审计日志队列绑定
     */
    @Bean
    public Binding auditLogBinding() {
        return BindingBuilder
                .bind(auditLogQueue())
                .to(userOperationExchange())
                .with(auditRoutingKey);
    }

    /**
     * 登录日志队列绑定
     */
    @Bean
    public Binding loginLogBinding() {
        return BindingBuilder
                .bind(loginLogQueue())
                .to(userOperationExchange())
                .with(loginRoutingKey);
    }

    /**
     * 通知队列绑定
     */
    @Bean
    public Binding notificationBinding() {
        return BindingBuilder
                .bind(notificationQueue())
                .to(userOperationExchange())
                .with(notificationRoutingKey);
    }

    /**
     * 审计日志死信队列绑定
     */
    @Bean
    public Binding auditLogDeadLetterBinding() {
        return BindingBuilder
                .bind(auditLogDeadLetterQueue())
                .to(dlxExchange())
                .with(AUDIT_LOG_DLQ);
    }

    /**
     * 登录日志死信队列绑定
     */
    @Bean
    public Binding loginLogDeadLetterBinding() {
        return BindingBuilder
                .bind(loginLogDeadLetterQueue())
                .to(dlxExchange())
                .with(LOGIN_LOG_DLQ);
    }

    /**
     * 通知死信队列绑定
     */
    @Bean
    public Binding notificationDeadLetterBinding() {
        return BindingBuilder
                .bind(notificationDeadLetterQueue())
                .to(dlxExchange())
                .with(NOTIFICATION_DLQ);
    }

    /**
     * RabbitTemplate配置
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        
        // 设置JSON消息转换器
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        
        // 设置交换机
        template.setExchange(userOperationExchange);
        
        // 消息确认机制
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.debug("消息发送成功: {}", correlationData);
            } else {
                log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
            }
        });
        
        // 消息返回机制
        template.setReturnsCallback(returned -> {
            log.error("消息未路由到队列: {}, 交换机: {}, 路由键: {}, 响应码: {}, 响应文本: {}",
                    returned.getMessage(), returned.getExchange(), returned.getRoutingKey(),
                    returned.getReplyCode(), returned.getReplyText());
        });
        
        // 设置mandatory为true，确保消息能够被路由到队列
        template.setMandatory(true);
        
        log.info("RabbitTemplate配置完成");
        return template;
    }

    /**
     * 消息监听容器工厂配置
     */
    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        
        // 设置JSON消息转换器
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        
        // 并发配置
        factory.setConcurrentConsumers(2);
        factory.setMaxConcurrentConsumers(8);
        
        // 预取数量
        factory.setPrefetchCount(50);
        
        // 默认不重新排队
        factory.setDefaultRequeueRejected(false);
        
        // 消费者确认模式
        factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
        
        // 重试配置
        factory.setAdviceChain(
            org.springframework.retry.interceptor.RetryInterceptorBuilder
                .stateless()
                .maxAttempts(3)
                .backOffOptions(1000, 2.0, 10000) // 初始间隔1s，乘数2.0，最大间隔10s
                .build()
        );
        
        log.info("RabbitMQ监听容器工厂配置完成");
        return factory;
    }

    /**
     * 管理员配置（可选，用于创建队列和交换机）
     */
    @Bean
    public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
        return new org.springframework.amqp.rabbit.core.RabbitAdmin(connectionFactory);
    }
}
